/* Copyright 2021 Kerim Yalcin
**
**   Licensed under the Apache License, Version 2.0 (the "License");
**   you may not use this file except in compliance with the License.
**   You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
**   Unless required by applicable law or agreed to in writing, software
**   distributed under the License is distributed on an "AS IS" BASIS,
**   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
**   See the License for the specific language governing permissions and
**   limitations under the License.
*/

#include "WindowBase.hpp"
#include <iostream>

/***** public *****/

Agx::WindowBase::WindowBase(HINSTANCE pInstance) :
    mInstance {pInstance}
{
    mIsCreated = false;
    mIsLinked_withFrame = false;
    mHwnd = nullptr;
    mRect = {0};
}

HINSTANCE Agx::WindowBase::get_Instance() const {
    return mInstance;
}

HWND Agx::WindowBase::get_WindowHandle() const {
    return mHwnd;
}

const bool& Agx::WindowBase::is_linked_withFrame() {
    return mIsLinked_withFrame;
}

const bool& Agx::WindowBase::is_created() {
    return mIsCreated;
}

void Agx::WindowBase::set_Width(const int& pWidth) {
    mWindow_Width = pWidth;
}

void Agx::WindowBase::set_Heigth(const int& pHeight) {
    mWindow_Heigth = pHeight;
}

void Agx::WindowBase::change_Width(const int& pWidth_toChange) {
    if (is_linked_withFrame()) {
        mWindow_Width = pWidth_toChange;

        GetWindowRect(get_WindowHandle(), &mRect);
        const int width = mRect.right-mRect.left;
        const int del_width = width-pWidth_toChange;

        if (pWidth_toChange == width) {
            return;
        }
        else  {
            int del_half_width = (del_width-del_width%2)/2;
            mRect.left+=del_half_width;
        }

        SetWindowPos(
            get_WindowHandle(),
            0,
            mRect.left,
            mRect.top,
            pWidth_toChange,
            mWindow_Heigth,
            SWP_NOZORDER
        );
    }
}

void Agx::WindowBase::change_Heigth(const int& pHeigth_toChange) {
    if (is_linked_withFrame()) {
        mWindow_Heigth = pHeigth_toChange;

        GetWindowRect(get_WindowHandle(), &mRect);
        const int heigth = mRect.bottom-mRect.top;
        const int del_heigth = heigth-pHeigth_toChange;

        if (pHeigth_toChange == heigth) {
            return;
        }
        else  {
            int del_half_heigth = (del_heigth-del_heigth%2)/2;
            mRect.top+=del_half_heigth;
        }

        SetWindowPos(
            get_WindowHandle(),
            0,
            mRect.left,
            mRect.top,
            mWindow_Width,
            pHeigth_toChange,
            SWP_NOZORDER
        );
    }
}

void Agx::WindowBase::set_X_Position(const int& pX_Pos) {
    mPosition_X = pX_Pos;
}

void Agx::WindowBase::change_X_Position(const int& pX_Pos_toChange) {
    if (is_linked_withFrame()) {
        mPosition_X = pX_Pos_toChange;

        GetWindowRect(get_WindowHandle(), &mRect);

        SetWindowPos(
            get_WindowHandle(),
            0,
            pX_Pos_toChange,
            mRect.top,
            0,
            0,
            SWP_NOZORDER | SWP_NOSIZE
        );
    }
}

void Agx::WindowBase::set_Y_Position(const int& pY_Pos) {
    mPosition_Y = pY_Pos;
}

void Agx::WindowBase::change_Y_Position(const int& pY_Pos_toChange) {
    if (is_linked_withFrame()) {
        mPosition_Y = pY_Pos_toChange;

        GetWindowRect(get_WindowHandle(), &mRect);

        SetWindowPos(
            get_WindowHandle(),
            0,
            mRect.left,
            pY_Pos_toChange,
            0,
            0,
            SWP_NOZORDER | SWP_NOSIZE
        );
    }
}

const int& Agx::WindowBase::get_Width() {
    if (is_linked_withFrame()) {
        GetWindowRect(mHwnd, &mRect);
        mWindow_Width = mRect.right-mRect.left;
    }
    return mWindow_Width;
}

const int& Agx::WindowBase::get_Heigth() { 
    if (is_linked_withFrame()) {
        GetWindowRect(mHwnd, &mRect);
        mWindow_Heigth = mRect.bottom-mRect.top;
    }
    return mWindow_Heigth; 
}

const int& Agx::WindowBase::get_X_Position() {
    if (is_linked_withFrame()) {
        GetWindowRect(mHwnd, &mRect);
        mPosition_X = mRect.left;
    }
    return mPosition_X;
}

const int& Agx::WindowBase::get_Y_Position() {
    if (is_linked_withFrame()) {
        GetWindowRect(mHwnd, &mRect);
        mPosition_Y = mRect.top;
    }
    return mPosition_Y;
}

HWND Agx::WindowBase::get_Parent() const {
    return mHwnd;
}

void Agx::WindowBase::show() {
    if (mIsLinked_withFrame) {
        ShowWindow(mHwnd, SW_SHOW);
    }
}

void Agx::WindowBase::create(LONG_PTR pWindowFrame) {
    mHwnd = CreateWindowExA(
        mExtendedStyle,
        mWndClass_Name.c_str(),
        mWindow_Name.c_str(),
        mStyle,
        mPosition_X,
        mPosition_Y,
        mWindow_Width,
        mWindow_Heigth,
        mWindow_Parent,
        mMenu,
        mInstance,
        mParam
    );

    if (mHwnd) {
        mIsCreated = true;
        SetWindowLongPtrA(mHwnd, GWLP_USERDATA, pWindowFrame);
        if (pWindowFrame == GetWindowLongPtrA(mHwnd, GWLP_USERDATA)) {
            mIsLinked_withFrame = true;
        }

        RECT rect = {0};
        GetWindowRect(get_WindowHandle(), &rect);
        
        mWindow_Width = rect.right-rect.left;
        mWindow_Heigth = rect.bottom-rect.top;
        mPosition_X = rect.left;
        mPosition_Y = rect.top;
    }
}